#include <algorithm>
#include <math.h>
#include <iostream>
#include "related_products.h"

RelatedProducts::RelatedProducts(map<string, set<string> > product_user_set_map, size_t max_recommend_num)
{
    set<string> intersect;
    float simiarity;
    float denominator;
    int count = 0;
    bool init_set = false;
    for (map<string, set<string> >::iterator it = product_user_set_map.begin(); it != product_user_set_map.end(); ++it)
    {
        count++;
        if (count % 1000 == 0)
            cout << "have computed " << count << " products!" << endl;
        init_set = false;
        for (map<string, set<string> >::iterator ip = product_user_set_map.begin(); ip != product_user_set_map.end(); ++ip)
        {
            intersect.clear();
            if (ip == it)
                continue;
            set_intersection(it->second.begin(), it->second.end(), ip->second.begin(), ip->second.end(), inserter(intersect, intersect.begin()));
            denominator = sqrt(it->second.size() * ip->second.size());
            if (denominator == 0)
                simiarity = 0;
            else
                simiarity = float(intersect.size()) / denominator;
            if (simiarity > 0)
            {
                if (init_set == false)
                {
                    related_products_map[it->first] = SimilarProductsQueue (ProductSimilarityPairCompare(true));
                    init_set = true;
                }
                if (related_products_map[it->first].size() < max_recommend_num)
                {
                    ProductSimilarityPair tmp_pair(ip->first, simiarity);
                    related_products_map[it->first].push(tmp_pair);
                }
                else
                {
                    if (related_products_map[it->first].top().second < simiarity)
                    {
                        related_products_map[it->first].pop();
                        ProductSimilarityPair tmp_pair(ip->first, simiarity);
                        related_products_map[it->first].push(tmp_pair);
                    }
                }
            }
        }
    }
}
